#ifndef QOS_CPP_HIGH_PRECISION_TIMER
#define QOS_CPP_HIGH_PRECISION_TIMER

#include "types.hpp"
#include "clock.hpp"
#include "timer.hpp"
#include <chrono>
#include <limits>

namespace qOS {

    /** @addtogroup qstimers Timers
    * @brief High precision timer extension for microsecond-level timing
    * @pre This extension requires the operating system is previously initialized
    * with core::init() with a functional time-base.
    * @note This implementation follows functional safety standards (ISO 26262, IEC 61508)
    *  @{
    */

    /**
    * @brief A high-precision non-blocking Timer object
    * @details HighPrecisionTimer extends the basic timer functionality to provide
    * microsecond-level precision timing using modern C++ chrono facilities.
    * This timer is fully compatible with the existing timer class and can be
    * used as a drop-in replacement for applications requiring higher timing
    * precision.
    * 
    * The timer uses a combination of system clock and high-resolution clock
    * to achieve microsecond accuracy while maintaining compatibility with
    * the cooperative RTOS environment.
    * 
    * @note Functional Safety Compliance:
    * - No dynamic memory allocation
    * - Bounded execution time
    * - Deterministic behavior
    * - Error detection and handling
    * - No floating-point operations
    */
    class HighPrecisionTimer {
    private:
        std::chrono::microseconds interval{0};          /**< Timer interval in microseconds */
        std::chrono::steady_clock::time_point startTime; /**< Start time point */
        bool armed{false};                              /**< Timer armed status */
        bool errorState{false};                         /**< Error state for safety monitoring */
        
        /**
         * @brief Get current time in microseconds
         * @return Current time in microseconds
         */
        uint64_t getCurrentMicroseconds() const noexcept {
            std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
            std::chrono::microseconds duration = std::chrono::duration_cast<std::chrono::microseconds>(
                now.time_since_epoch());
            return duration.count();
        }
        
        /**
         * @brief Convert duration_t to microseconds
         * @param duration Duration to convert
         * @return Duration in microseconds
         */
        uint64_t durationToMicroseconds(duration_t duration) const noexcept {
            // duration_t is in microseconds, no conversion needed
            return static_cast<uint64_t>(duration);
        }
        
        /**
         * @brief Convert microseconds to duration_t
         * @param microseconds Time in microseconds
         * @return Duration in duration_t (microseconds)
         */
        duration_t microsecondsToDuration(uint64_t microseconds) const noexcept {
            return static_cast<duration_t>(microseconds);
        }
        
        /**
         * @brief Check for arithmetic overflow in time calculations
         * @param a First value
         * @param b Second value
         * @return true if overflow would occur, false otherwise
         */
        bool checkOverflow(uint64_t a, uint64_t b) const noexcept {
            return (a > std::numeric_limits<uint64_t>::max() - b);
        }
        
        /**
         * @brief Safe time subtraction with overflow checking
         * @param a Minuend
         * @param b Subtrahend
         * @param result Result of subtraction
         * @return true if successful, false if underflow
         */
        bool safeSubtract(uint64_t a, uint64_t b, uint64_t& result) const noexcept {
            if (b > a) {
                result = 0;
                return false;
            }
            result = a - b;
            return true;
        }

    public:
        /**
        * @brief Default constructor
        */
        HighPrecisionTimer() noexcept {
            disarm();
        }
        
        /**
        * @brief Constructor with initial interval
        * @param tTime Initial expiration time in microseconds
        */
        explicit HighPrecisionTimer(const duration_t tTime) {
            set(tTime);
        }
        
        /**
        * @brief Destructor
        */
        virtual ~HighPrecisionTimer() {}
        
        /**
        * @brief Set the expiration time for the timer
        * @param tTime Expiration time in microseconds
        * @return true on success, false on failure
        */
        bool set(const duration_t tTime) noexcept {
            // Check for invalid time values
            if (tTime == 0 || tTime > MAX_TIMER_INTERVAL) {
                errorState = true;
                return false;
            }
            
            interval = std::chrono::microseconds(durationToMicroseconds(tTime));
            startTime = std::chrono::steady_clock::now();
            armed = true;
            errorState = false;
            return true;
        }
        
        /**
        * @brief Disarm the timer
        */
        void disarm() noexcept {
            armed = false;
            interval = std::chrono::microseconds(0);
            errorState = false;
        }
        
        /**
        * @brief Reload the timer with the previous interval
        */
        void reload() noexcept {
            if (armed) {
                startTime = std::chrono::steady_clock::now();
                errorState = false;
            }
        }
        
        /**
        * @brief Get the current status of the timer
        * @return true if armed, false if disarmed
        */
        bool status() const noexcept {
            return armed && !errorState;
        }
        
        /**
        * @brief Check if timer has expired with automatic reload
        * @param tTime New interval (optional)
        * @return true if expired, false otherwise
        */
        bool reloadIfExpired(const duration_t tTime = 0) noexcept {
            if (errorState) {
                return false;
            }
            
            if (!armed) {
                if (tTime > 0) {
                    return set(tTime);
                }
                return false;
            }
            
            if (expired()) {
                if (tTime > 0) {
                    set(tTime);
                } else {
                    reload();
                }
                return true;
            }
            return false;
        }
        
        /**
        * @brief Check if timer has expired with automatic reload (no parameter)
        * @return true if expired, false otherwise
        */
        bool reloadIfExpired(void) noexcept {
            return reloadIfExpired(0);
        }
        
        /**
        * @brief Get remaining time
        * @return Remaining time in microseconds
        */
        clock_t remaining() const noexcept {
            if (!armed || errorState) {
                return REMAINING_IN_DISARMED_STATE;
            }
            
            std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
            std::chrono::microseconds elapsed = std::chrono::duration_cast<std::chrono::microseconds>(
                now - startTime);
            
            if (elapsed >= interval) {
                return 0;
            }
            
            std::chrono::microseconds remainingMicros = interval - elapsed;
            return microsecondsToDuration(remainingMicros.count());
        }
        
        /**
        * @brief Get elapsed time
        * @return Elapsed time in microseconds
        */
        clock_t elapsed() const noexcept {
            if (!armed || errorState) {
                return 0;
            }
            
            std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
            std::chrono::microseconds elapsed = std::chrono::duration_cast<std::chrono::microseconds>(
                now - startTime);
            return microsecondsToDuration(elapsed.count());
        }
        
        /**
        * @brief Check if timer has expired
        * @return true if expired, false otherwise
        */
        bool expired() const noexcept {
            if (!armed || errorState) {
                return false;
            }
            
            std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
            std::chrono::microseconds elapsed = std::chrono::duration_cast<std::chrono::microseconds>(
                now - startTime);
            return elapsed >= interval;
        }
        
        /**
        * @brief Check if deadline has been reached
        * @return true if deadline reached, false otherwise
        */
        bool deadLineCheck() const noexcept {
            return expired();
        }
        
        /**
        * @brief Get the timer interval
        * @return Interval in microseconds
        */
        clock_t getInterval() const noexcept {
            return microsecondsToDuration(interval.count());
        }
        
        /**
        * @brief Check if timer is in error state
        * @return true if error state, false otherwise
        */
        bool hasError() const noexcept {
            return errorState;
        }
        
        /**
        * @brief Clear error state
        */
        void clearError() noexcept {
            errorState = false;
        }
        
        /**
        * @brief Assignment operator for duration
        * @param tTime New interval
        * @return Reference to this timer
        */
        HighPrecisionTimer& operator=(const duration_t tTime) {
            set(tTime);
            return *this;
        }
        
        /**
        * @brief Assignment operator for boolean (arm/disarm)
        * @param en true to reload, false to disarm
        * @return Reference to this timer
        */
        HighPrecisionTimer& operator=(const bool en) {
            if (en) {
                reload();
            } else {
                disarm();
            }
            return *this;
        }
        
        /**
        * @brief Function call operator (check expiration)
        * @return true if expired, false otherwise
        */
        bool operator()() const {
            return expired();
        }
        
        /**
        * @brief Function call operator with new interval
        * @param tTime New interval
        * @return true if operation successful
        */
        bool operator()(const duration_t tTime) {
            return set(tTime);
        }
        
        /**
        * @brief Function call operator for arm/disarm
        * @param en true to reload, false to disarm
        */
        void operator()(const bool en) {
            if (en) {
                reload();
            } else {
                disarm();
            }
        }
        
        /**
        * @brief Boolean conversion operator
        * @return true if expired, false otherwise
        */
        explicit operator bool() const noexcept {
            return expired();
        }
        
        /**
        * @brief High-precision delay function
        * @param microseconds Delay time in microseconds
        */
        static void delayMicroseconds(uint64_t microseconds) noexcept {
            if (microseconds == 0 || microseconds > MAX_DELAY_MICROSECONDS) {
                return;
            }
            
            std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
            std::chrono::steady_clock::time_point target = start + std::chrono::microseconds(microseconds);
            
            while (std::chrono::steady_clock::now() < target) {
                // Busy wait for maximum precision
                // In a real RTOS, this would yield to other tasks
                asm volatile("" : : : "memory");
            }
        }
        
        /**
        * @brief High-precision delay function using duration_t
        * @param duration Delay time in microseconds
        */
        static void delay(const duration_t duration) noexcept {
            delayMicroseconds(static_cast<uint64_t>(duration));
        }
        
        /**
        * @brief Get current time in microseconds
        * @return Current time in microseconds since epoch
        */
        static uint64_t getMicroseconds() noexcept {
            std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
            std::chrono::microseconds duration = std::chrono::duration_cast<std::chrono::microseconds>(
                now.time_since_epoch());
            return duration.count();
        }
        
        /**
        * @brief Get current time in nanoseconds
        * @return Current time in nanoseconds since epoch
        */
        static uint64_t getNanoseconds() noexcept {
            std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
            std::chrono::nanoseconds duration = std::chrono::duration_cast<std::chrono::nanoseconds>(
                now.time_since_epoch());
            return duration.count();
        }
        
        // Safety-related constants
        static const bool ARMED = true;
        static const bool DISARMED = false;
        static const clock_t DISARM_VALUE = 0;
        static const clock_t REMAINING_IN_DISARMED_STATE = 0xFFFFFFFFUL;
        static const duration_t MAX_TIMER_INTERVAL = 3600000000UL; // 1 hour in microseconds
        static const uint64_t MAX_DELAY_MICROSECONDS = 60000000UL; // 1 minute in microseconds
    };

    /** @}*/
}

// Compatibility operators
bool operator==(const qOS::HighPrecisionTimer& obj, bool value) {
    return obj.expired() == value;
}

#endif /* QOS_CPP_HIGH_PRECISION_TIMER */